﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using Moq;

namespace MvcWiki.Test.Repository.FileSystem.WikiPageFileSystemRepository
{
    public class UpdateEntityFacts
    {
        [Fact]
        public void Checks_Whether_Namespace_Directory_Exists()
        {
            var wikiPage = new MvcWiki.Model.WikiPage
            {
                Name = "Page",
                Namespace = new MvcWiki.Model.WikiNamespace { Name = "Namespace" }
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*"))
                .Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.GetDirectories("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc", String.Format("*---{0}", wikiPage.Id)))
                .Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiPageRepository = new MvcWiki.Repository.FileSystem.WikiPageFileSystemRepository(repositoryFactory.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            wikiPageRepository.UpdateEntity(wikiPage);

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Throws_Exception_If_Namespace_Directory_Does_Not_Exist()
        {
            var wikiPage = new MvcWiki.Model.WikiPage
            {
                Name = "Page",
                Namespace = new MvcWiki.Model.WikiNamespace { Name = "Namespace" }
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*"))
                .Returns(new string[] { });

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiPageRepository = new MvcWiki.Repository.FileSystem.WikiPageFileSystemRepository(repositoryFactory.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            Assert.Throws<MvcWiki.Exceptions.NamespaceDoesNotExistException>(
                () => wikiPageRepository.UpdateEntity(wikiPage));
        }

        [Fact]
        public void Checks_Whether_Page_Directory_Exists()
        {
            var wikiPage = new MvcWiki.Model.WikiPage
            {
                Name = "Page",
                Namespace = new MvcWiki.Model.WikiNamespace { Name = "Namespace" }
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*"))
                .Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.GetDirectories("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc", String.Format("*---{0}", wikiPage.Id)))
                .Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiPageRepository = new MvcWiki.Repository.FileSystem.WikiPageFileSystemRepository(repositoryFactory.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            wikiPageRepository.UpdateEntity(wikiPage);

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Throws_Exception_If_Page_Directory_Does_Not_Exist()
        {
            var wikiPage = new MvcWiki.Model.WikiPage
            {
                Name = "Page",
                Namespace = new MvcWiki.Model.WikiNamespace { Name = "Namespace" }
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*"))
                .Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.GetDirectories("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc", "Page---*"))
                .Returns(new string[] { });

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiPageRepository = new MvcWiki.Repository.FileSystem.WikiPageFileSystemRepository(repositoryFactory.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            Assert.Throws<MvcWiki.Exceptions.PageDoesNotExistException>(
                () => wikiPageRepository.UpdateEntity(wikiPage));
        }

        [Fact]
        public void Renames_Page_Directory_If_Name_Has_Been_Changed()
        {
            var wikiPage = new MvcWiki.Model.WikiPage
            {
                Name = "Page",
                Namespace = new MvcWiki.Model.WikiNamespace { Name = "Namespace" }
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.GetDirectories("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc", String.Format("*---{0}", wikiPage.Id))).Returns(new string[] { String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\PageOld---{0}", wikiPage.Id) });
            fileSystem.Setup(x => x.MoveDirectory(String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\PageOld---{0}", wikiPage.Id), String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}", wikiPage.Id)));

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiPageRepository = new MvcWiki.Repository.FileSystem.WikiPageFileSystemRepository(repositoryFactory.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            wikiPageRepository.UpdateEntity(wikiPage);

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Gets_All_Revision_Txt_Files()
        {
            var wikiPage = new MvcWiki.Model.WikiPage
            {
                Name = "Page",
                Namespace = new MvcWiki.Model.WikiNamespace { Name = "Namespace" },
                Revisions = new List<MvcWiki.Model.WikiPageRevision> { }
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.GetDirectories("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc", String.Format("*---{0}", wikiPage.Id))).Returns(new string[] { String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}", wikiPage.Id) });

            var files = new string[] {
                String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}\\r---20090101010000.txt", wikiPage.Id),
                String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}\\r---20090101010100.txt", wikiPage.Id),
                String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}\\r---20090101010200.txt", wikiPage.Id)
            };

            fileSystem.Setup(x => x.GetFiles(String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}", wikiPage.Id), "r---*.txt")).Returns(files);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiPageRepository = new MvcWiki.Repository.FileSystem.WikiPageFileSystemRepository(repositoryFactory.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            wikiPageRepository.UpdateEntity(wikiPage);

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Removes_Revision_Txt_Files_Which_Are_Not_In_WikiPage()
        {
            var wikiPage = new MvcWiki.Model.WikiPage
            {
                Name = "Page",
                Namespace = new MvcWiki.Model.WikiNamespace { Name = "Namespace" },
                Revisions = new List<MvcWiki.Model.WikiPageRevision> {
                    new MvcWiki.Model.WikiPageRevision(new DateTime(2009, 01, 01, 01, 00, 00, DateTimeKind.Utc), "Revision1"),
                    new MvcWiki.Model.WikiPageRevision(new DateTime(2009, 01, 01, 01, 01, 00, DateTimeKind.Utc), "Revision2")
                }
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.GetDirectories("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc", String.Format("*---{0}", wikiPage.Id))).Returns(new string[] { String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}", wikiPage.Id) });

            var files = new string[] {
                String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}\\r---20090101010000.txt", wikiPage.Id),
                String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}\\r---20090101010100.txt", wikiPage.Id),
                String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}\\r---20090101010200.txt", wikiPage.Id)
            };

            fileSystem.Setup(x => x.GetFiles(String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}", wikiPage.Id), "r---*.txt")).Returns(files);
            fileSystem.Setup(x => x.DeleteFile(String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}\\r---20090101010200.txt", wikiPage.Id)));
                
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiPageRepository = new MvcWiki.Repository.FileSystem.WikiPageFileSystemRepository(repositoryFactory.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            wikiPageRepository.UpdateEntity(wikiPage);

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Writes_All_Revisions_Into_Txt_Files()
        {
            var wikiPage = new MvcWiki.Model.WikiPage
            {
                Name = "Page",
                Namespace = new MvcWiki.Model.WikiNamespace { Name = "Namespace" },
                Revisions = new List<MvcWiki.Model.WikiPageRevision> {
                    new MvcWiki.Model.WikiPageRevision(new DateTime(2009, 01, 01, 01, 00, 00, DateTimeKind.Utc), "Revision1"),
                    new MvcWiki.Model.WikiPageRevision(new DateTime(2009, 01, 01, 01, 01, 00, DateTimeKind.Utc), "Revision2"),
                    new MvcWiki.Model.WikiPageRevision(new DateTime(2009, 01, 01, 01, 02, 00, DateTimeKind.Utc), "Revision3")
                }
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.GetDirectories("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc", String.Format("*---{0}", wikiPage.Id))).Returns(new string[] { String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}", wikiPage.Id) });

            fileSystem.Setup(x => x.GetFiles(String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}", wikiPage.Id), "r---*.txt")).Returns(new string[] { });
            fileSystem.Setup(x => x.WriteToFile(String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}\\r---20090101010000.txt", wikiPage.Id), "Revision1"));
            fileSystem.Setup(x => x.WriteToFile(String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}\\r---20090101010100.txt", wikiPage.Id), "Revision2"));
            fileSystem.Setup(x => x.WriteToFile(String.Format("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\Page---{0}\\r---20090101010200.txt", wikiPage.Id), "Revision3"));

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiPageRepository = new MvcWiki.Repository.FileSystem.WikiPageFileSystemRepository(repositoryFactory.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            wikiPageRepository.UpdateEntity(wikiPage);

            fileSystem.VerifyAll();
        }
    }
}